﻿-- Author      : yx
-- Create Date : 2009/10/17 19:41:49

-- {{{ indicator frames
local gridSize = 10
local idFrms = {}
local totalFrmCount = 64
local targetChanged = false;
local lastTargetGUID = nil;
local lastX = nil
local lastY = nil
local ndx = 0
local ndy = 0
combatRangeSpell = nil;
CombatSpells = {  };
BuffSpells = {  };
BuffAndTriggeredSpells = {  };
HealSpells = {  };
checkRangeSpell = nil;

-- ID: 1-3: Health: 4-5; Mana: 6-7; MapPosX: 8-13; MapPosY: 14-19; MapAreaID: 20-22;
-- InCombat, dead, isGhost: 23; TargetIsEnemy, TargetIsPlayer, TargetIsDead: 24;
-- TargetHealthPercent: 25-26; TargetManaPercent: 27-28; 
-- TargetInCombatRange, lastChanged, TargetTooFar, BagIsFull, FocusIsDead, HasFocus ...: 29-30;
-- SpellCastable[...]: 31-32;
-- BuffStates[...]: 33-34;
-- SpellCastTriggers[...]: 35-36;
-- dx, dy: 37-39, 40-42;
-- Silver coins: 43-48;
-- }}} indicator frames

function showmsg( msg )
	DEFAULT_CHAT_FRAME:AddMessage( msg, 1, 1, 0 );
end

function GetAllBagsFreeSlotNum()
	local result = 0;
	for i = 0, 4, 1 do
		numberOfFreeSlots, BagType = GetContainerNumFreeSlots(i);
		if BagType==0 then
			result = result + numberOfFreeSlots;
		end
	end
	return result;
end

function MakeIndicatorFrame( index )
	local frm = CreateFrame( "Frame" )
	frm:SetWidth(gridSize)
	frm:SetHeight(gridSize)
	frm:SetPoint( "TOPLEFT", index*gridSize, 0 )
	frm.texture = frm:CreateTexture()
	frm.texture:SetAllPoints( frm )
	frm.texture:SetTexture( 255, 255, 255 )
	return frm
end

function UpdateLifeFrm()
	PresentNumber( 63*UnitHealth("player")/UnitHealthMax("player"), 4, 2 )
	PresentNumber( 63*UnitMana("player")/UnitManaMax("player"), 6, 2 )
end

function UpdateMapPosFrms()
	SetMapToCurrentZone()
	local xPos, yPos = GetPlayerMapPosition("player")
	PresentNumber( 262143*xPos, 8, 6 )
	PresentNumber( 262143*yPos, 14, 6 )
	PresentNumber( GetCurrentMapAreaID(), 20, 3 )
end

function UpdateCombatFrms()
	local flag = 0
	if UnitAffectingCombat("player")==1 then
		flag = flag + 1
	end
	if UnitIsDead("player")==1 then
		flag = flag + 2
	end
	if UnitIsGhost("player")==1 then
		flag = flag + 4
	end
	
	PresentNumber( flag, 23, 1 )
	
	flag = 0
	if UnitIsEnemy("player", "target") then
		flag = flag + 1
	end
	if UnitIsPlayer("target")==1 then
		flag = flag + 2
	end
	if UnitIsDead("target")==1 then
		flag = flag + 4
	end
	
	PresentNumber( flag, 24, 1 )
	
	local targetHealthPercent = UnitHealth("target")/UnitHealthMax("target");
	local targetManaPercent = UnitMana("target")/UnitManaMax("target");
	PresentNumber( 63*targetHealthPercent, 25, 2 )
	PresentNumber( 63*targetManaPercent, 27, 2 )
	
	-- Below is Spell checking flags.
	-- 
	flag = 0
	if IsSpellInRange(combatRangeSpell, "target")==1 then
		flag = flag + 1
	end
	
	if targetChanged==false then
		local curTarget = UnitGUID( "target" );
		if lastTargetGUID==nil and curTarget~=nil then
			lastTargetGUID = curTarget
		else
			if curTarget~=nil and lastTargetGUID~=nil and lastTargetGUID~=curTarget then
				targetChanged = true
			end
		end
		
	end
	if targetChanged==true then
		flag = flag + 2;
	end
	
	if IsSpellInRange( checkRangeSpell, "target" )~=1 then
		flag = flag + 4;
	end
	
	-- Bag is full
	if GetAllBagsFreeSlotNum()==0 then
		flag = flag + 8;
	end
	
	if UnitIsDead( "focus" )==1 then
		flag = flag + 16
	end
	
	if UnitExists( "focus" )==1 then
		flag = flag + 32
	end
	
	PresentNumber( flag, 29, 2 )
	
	-- combat spell castable
	flag = 0;
	local curTag = 1;
	for i = 1, 6, 1 do
		if (CombatSpells[i]~=nil) then
			local start, duration, enabled = GetSpellCooldown(CombatSpells[i]); 
			if ( ( ( CombatSpells[i]=="神圣风暴" or CombatSpells[i]=="奉献" ) and UnitIsEnemy("player", "target") and UnitHealth("target")>0 )
			 or ( IsSpellInRange( CombatSpells[i], "target" )==1 ) )
			 and enabled==1 and duration<=0 and start<=0
				and ( CombatSpells[i]~="愤怒之锤" or targetHealthPercent<0.2 ) then
				if CombatSpells[i]=="公正审判" or CombatSpells[i]=="奉献" then
					if targetHealthPercent>0.2 then
						flag = flag + curTag;
					end
				else
					flag = flag + curTag;
				end
			end
		end
		curTag = curTag*2;
	end
	
	PresentNumber( flag, 31, 2 )
	
	-- buff states
	flag = 0;
	curTag = 1;
	for i = 1, 4, 1 do
		if (BuffSpells[i]~=nil) then
			if UnitBuff( "player", BuffSpells[i] )==nil then
				flag = flag + curTag;
			end
		end
		curTag = curTag*2;
	end
	
	PresentNumber( flag, 33, 2 )
	
	
	-- Spell cast triggers
	flag = 0;
	curTag = 1;
	for i = 1, 2, 1 do
		if (BuffAndTriggeredSpells[i]~=nil) then
			if BuffAndTriggeredSpells[i][1]=="healthcheck" then
				if (UnitHealth("player")/UnitHealthMax("player"))<BuffAndTriggeredSpells[i][3]/100 then
					flag = flag + curTag;
				end
			else
				if UnitBuff( "player", BuffAndTriggeredSpells[i][1] )~=nil then
					if BuffAndTriggeredSpells[i][1]=="战争艺术" then
						if (UnitHealth("player")/UnitHealthMax("player"))<0.9 then
							local start, duration, enabled = GetSpellCooldown(BuffAndTriggeredSpells[i][2]); 
							if enabled==1 and duration<=0 and start<=0 then
								flag = flag + curTag;
							end
						end
					else
						local start, duration, enabled = GetSpellCooldown(BuffAndTriggeredSpells[i][2]); 
						if enabled==1 and duration<=0 and start<=0 then
							flag = flag + curTag;
						end
					end
				end
			end
		end
		curTag = curTag*2;
	end
	
	PresentNumber( flag, 35, 2 )
		
	-- dx, dy
	local curX, curY = GetPlayerMapPosition( "player" )
	if lastX~=nil and lastY~=nil then
		local dx = curX - lastX;
		local dy = curY - lastY;
		if dx~=0 or dy~=0 then
			local mdxy
			if abs(dx)>abs(dy) then
				mdxy = abs(dx)
			else
				mdxy = abs(dy)
			end
			ndx = dx/mdxy;
			ndy = dy/mdxy;
		end
	end
	
	lastX = curX;
	lastY = curY;
	
	PresentNumber( (ndx+1.0)/2*511, 37, 3 )
	PresentNumber( (ndy+1.0)/2*511, 40, 3 )
	
	-- Silver coins
	PresentNumber( GetMoney()/100, 43, 6 );
	
end

function PresentNumber( number, startFrm, count )
	if ( startFrm<1 or startFrm+count-1>totalFrmCount ) then
		--showmsg( "frm index out of range!" )
		return
	end
	if ( number<0 or number>=8^count ) then
		--showmsg( "number "..number.." greater than "..count.." frms can present!" )
		return
	end
	number = math.floor( number+0.5 )
	for i = 1, count, 1 do
		local r = number%2
		number = floor(number/2)
		local g = number%2
		number = floor(number/2)
		local b = number%2
		number = floor(number/2)
		idFrms[startFrm+i-1].texture:SetTexture( r*255, g*255, b*255 )
	end
end

function InitializeIndicatorFrames()
	for i = 1, totalFrmCount, 1 do
	   idFrms[i] = MakeIndicatorFrame( i )
	end
	-- as an identifier of PlayerInfoIndicator.
	PresentNumber( 4, 1, 1 )
	PresentNumber( 2, 2, 1 )
	PresentNumber( 1, 3, 1 )
	
	local class, engclass = UnitClass("player");
	if engclass=="DRUID" then
		showmsg( "DRUID");
		combatRangeSpell = "愤怒";
		CombatSpells = { "愤怒" };
		BuffSpells = { "荆棘术", "野性印记" };
		BuffAndTriggeredSpells = {  };
		HealSpells = { "回春术" };
		checkRangeSpell = "愤怒";
	else
		showmsg( "PALADIN");
		combatRangeSpell = "圣光审判";
		CombatSpells = { "神圣风暴", "奉献", "愤怒之锤", "公正审判", "十字军打击", "驱邪术" };
		BuffSpells = { "力量祝福", "智慧圣印", "惩戒光环" };
		BuffAndTriggeredSpells = { { "战争艺术", "圣光闪现" }, { "healthcheck", "复仇之怒", 60 } };
		HealSpells = { "圣光术" };
		checkRangeSpell = "十字军打击";
		
		-- showmsg( "PALADIN");
		-- combatRangeSpell = "圣光审判";
		-- CombatSpells = { "神圣风暴", "愤怒之锤", "十字军打击", "智慧审判", "驱邪术" };
		-- BuffSpells = { "殉难圣印", "虔诚光环" };
		-- BuffAndTriggeredSpells = { };
		-- HealSpells = { "圣光术" };
		-- checkRangeSpell = "智慧审判";
	end
		
	-- player infos.
	UpdateLifeFrm()
	
	SetBindingClick( "CTRL-L", "piiActionButton", "nude" )
	for i = 1, 6, 1 do
		if CombatSpells[i]~=nil then
			SetBindingSpell( "F"..i, CombatSpells[i] )
		end
	end
	for i = 1, 4, 1 do
		if BuffSpells[i]~=nil then
			SetBindingSpell( "F"..(i+6), BuffSpells[i] )
		end
	end
	for i = 1, 2, 1 do
		if BuffAndTriggeredSpells[i]~=nil then
			SetBindingSpell( "F"..(i+10), BuffAndTriggeredSpells[i][2] )
		end
	end
	
end

function MainFrame_OnLoad()
	this:RegisterEvent( "PLAYER_ENTERING_WORLD" )
end

function MainFrame_OnEvent()
	if ( event == "PLAYER_ENTERING_WORLD" ) then
		InitializeIndicatorFrames()
	end
end

function piiActionButton_OnClick()
	targetChanged = false
	lastTargetGUID = nil
end

function MainFrame_OnUpdate()
	UpdateLifeFrm()
	UpdateMapPosFrms()
	UpdateCombatFrms()
end
